package com.zzyl.serve.service.impl;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huaweicloud.sdk.iotda.v5.IoTDAClient;
import com.huaweicloud.sdk.iotda.v5.model.ShowDeviceShadowRequest;
import com.huaweicloud.sdk.iotda.v5.model.ShowDeviceShadowResponse;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.framework.web.service.TokenService;
import com.zzyl.serve.domain.*;
import com.zzyl.serve.dto.MemberFamilyDto;
import com.zzyl.serve.dto.UserLoginRequestDto;
import com.zzyl.serve.dto.queryDeviceDataListByDayDto;
import com.zzyl.serve.mapper.DeviceDataMapper;
import com.zzyl.serve.service.*;
import com.zzyl.serve.util.ThreadLocalUtils;
import com.zzyl.serve.vo.DeviceDataVo;
import com.zzyl.serve.vo.LoginVo;
import com.zzyl.serve.vo.MyFamilyVo;
import com.zzyl.serve.vo.QueryServiceVo;
import io.jsonwebtoken.Claims;
import org.apache.xmlbeans.ThreadLocalUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zzyl.serve.mapper.FamilyMemberMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import javax.servlet.http.HttpServletRequest;

/**
 * 老人家属Service业务层处理
 * 
 * @author itheima
 * @date 2025-03-12
 */
@Service
public class FamilyMemberServiceImpl extends ServiceImpl<FamilyMemberMapper, FamilyMember> implements IFamilyMemberService
{
    @Autowired
    private FamilyMemberMapper familyMemberMapper;
    @Autowired
    private IElderService elderService;
    @Autowired
    private IBedService bedService;
    @Autowired
    private IRoomService  roomService;
    @Autowired
    private IDeviceService  deviceService;
    @Autowired
    private IoTDAClient client;

    @Autowired
    private DeviceDataMapper deviceDataMapper;

    /**
     * 查询老人家属
     * 
     * @param id 老人家属主键
     * @return 老人家属
     */
    @Override
    public FamilyMember selectFamilyMemberById(Long id)
    {
        return getById(id);
    }

    /**
     * 查询老人家属列表
     * 
     * @param familyMember 老人家属
     * @return 老人家属
     */
    @Override
    public List<FamilyMember> selectFamilyMemberList(FamilyMember familyMember)
    {
        return familyMemberMapper.selectFamilyMemberList(familyMember);
    }

    /**
     * 新增老人家属
     * 
     * @param familyMember 老人家属
     * @return 结果
     */
    @Override
    public int insertFamilyMember(FamilyMember familyMember)
    {
        return save(familyMember) ? 1 : 0;
    }

    /**
     * 修改老人家属
     * 
     * @param familyMember 老人家属
     * @return 结果
     */
    @Override
    public int updateFamilyMember(FamilyMember familyMember)
    {
        return updateById(familyMember) ? 1 : 0;
    }

    /**
     * 批量删除老人家属
     * 
     * @param ids 需要删除的老人家属主键
     * @return 结果
     */
    @Override
    public int deleteFamilyMemberByIds(Long[] ids)
    {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除老人家属信息
     * 
     * @param id 老人家属主键
     * @return 结果
     */
    @Override
    public int deleteFamilyMemberById(Long id)
    {
        return removeById(id) ? 1 : 0;
    }


    @Autowired
    private WechatService webschatService;

    @Autowired
    private TokenService tokenService;

    /**
     *  小程序端 用户登录的逻辑处理
     * @param dto
     * @return
     */
    @Override
    public LoginVo login(UserLoginRequestDto dto) {


        //1.根据code调用微信api获取apenId
        String openid = webschatService.getOpenid(dto.getCode());

        //2.根据openId查询数据库获取用户信息family_member表
        FamilyMember familyMember = getOne(
                new LambdaQueryWrapper<FamilyMember>()
                        .eq(FamilyMember::getOpenId, openid)
        );

        //3.调用微信api获取用户绑定手机号
        String phone = webschatService.getPhone(dto.getPhoneCode());
        
        
        //4.判断用户信息是否存在，如果不存在，则新增family_member表
        //5.存在则 修改family_member表数据
        if(ObjectUtil.isNull(familyMember)){
            // 新用户


            familyMember = new FamilyMember();
            familyMember.setPhone(phone);
            familyMember.setOpenId(openid);

            // 设置初始随机名称
            familyMember.setName("花开富贵" + DateUtils.getTime());

            save(familyMember);

        }else {
            // 老用户
            familyMember.setPhone(phone);
            updateById(familyMember);
        }

        
        //6.将用户id存入token中，并返回数据给前端
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", familyMember.getId());
        claims.put("nickName", familyMember.getName());
        String token = tokenService.createToken(claims);
        LoginVo loginVo = new LoginVo();
        loginVo.setToken(token);
        loginVo.setNickName(familyMember.getName());
        return loginVo;
    }

    /**
     * 添加绑定关系
     *
     * @param dto
     */
    @Override
    public void addFamily(MemberFamilyDto dto,HttpServletRequest request) {
        if (ObjectUtil.isEmpty(dto)){
            throw new BaseException("参数不能为空");
        }
        LambdaQueryWrapper<Elder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Elder::getIdCardNo,dto.getIdCard());
        queryWrapper.eq(Elder::getName,dto.getName());
        Elder elder = elderService.getOne(queryWrapper);
        //从登录中获取token，并解析
        if (ObjectUtil.isNull(elder)){
            throw new BaseException("老人信息不存在");
        }
        String token = tokenService.getToken(request);
        Claims claims = tokenService.parseToken(token);
        Long familyMemberId = Long.parseLong(claims.get("userId").toString());
        Long elderId = elder.getId();
        LocalDateTime createTime = LocalDateTime.now();
        String remark = dto.getRemark();
        familyMemberMapper.addFamily(familyMemberId,elderId,createTime,remark);
        
    }

    /**
     * 查询我的家人列表
     *
     * @param request
     * @return
     */
    @Override
    public List<MyFamilyVo> my(HttpServletRequest request) {
        ArrayList<MyFamilyVo> myFamilyVos = new ArrayList<>();
        String token = tokenService.getToken(request);
        Claims claims = tokenService.parseToken(token);
        Long familyMemberId = Long.parseLong(claims.get("userId").toString());
        List<Long> elderIds =  familyMemberMapper.selectForElderId(familyMemberId);
        elderIds.forEach(elderId->{
            FamilyMemberElder familyMemberElder =  familyMemberMapper.selectByFamilyMemberId(elderId);
            LambdaQueryWrapper<Elder> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Elder::getId,familyMemberElder.getElderId());
            Elder elder = elderService.getOne(queryWrapper);
            MyFamilyVo myFamilyVo = new MyFamilyVo();
            myFamilyVo.setElderName(elder.getName());
            myFamilyVo.setElderId(familyMemberElder.getElderId());
            myFamilyVo.setId(familyMemberElder.getId());
            myFamilyVo.setFamilyMemberId(familyMemberElder.getFamilyMemberId());
            myFamilyVos.add(myFamilyVo);
        });
        return myFamilyVos;
    }

    /**
     * 分页查询
     *
     * @param request
     * @return
     */
    @Override
    public List<PageVo> listByPage(HttpServletRequest request) {
        ArrayList<PageVo> pageVos = new ArrayList<>();
        String token = tokenService.getToken(request);
        Claims claims = tokenService.parseToken(token);
        Long familyMemberId = Long.parseLong(claims.get("userId").toString());
        List<Long> elderIds =  familyMemberMapper.selectForElderId(familyMemberId);
        elderIds.forEach(elderId->{
            PageVo pageVo = new PageVo();
            FamilyMemberElder familyMemberElder =  familyMemberMapper.selectByFamilyMemberId(elderId);
            LambdaQueryWrapper<Elder> elderQueryWrapper = new LambdaQueryWrapper<>();
            elderQueryWrapper.eq(Elder::getId,familyMemberElder.getElderId());
            Elder elder = elderService.getOne(elderQueryWrapper);
            pageVo.setMid(familyMemberElder.getId());
            pageVo.setMremark(familyMemberElder.getRemark());
            pageVo.setElderId(elder.getId());
            pageVo.setName(elder.getName());
            pageVo.setImage(elder.getImage());
            pageVo.setBedNumber(elder.getBedNumber());
            LambdaQueryWrapper<Bed> bedQueryWrapper = new LambdaQueryWrapper<>();
            bedQueryWrapper.eq(Bed::getId,elder.getBedId());
            Bed bed = bedService.getOne(bedQueryWrapper);
            LambdaQueryWrapper<Room> roomQueryWrapper = new LambdaQueryWrapper<>();
            roomQueryWrapper.eq(Room::getId,bed.getRoomId());
            Room room = roomService.getOne(roomQueryWrapper);
            pageVo.setTypeName(room.getTypeName());
            LambdaQueryWrapper<Device> deviceQueryWrapper = new LambdaQueryWrapper<>();
            deviceQueryWrapper.eq(Device::getRemark,elder.getName());
            Device device = deviceService.getOne(deviceQueryWrapper);
            if (ObjectUtil.isNull(device)){
                pageVo.setIotId("");
                pageVo.setDeviceName("");
                pageVo.setProductKey("");
            }else {
                pageVo.setIotId(device.getIotId());
                pageVo.setDeviceName(device.getDeviceName());
                pageVo.setProductKey(device.getProductKey());
            }
            pageVos.add(pageVo);
        });
        return pageVos;
    }

    /**
     * 查询健康数据
     *
     * @param iotId
     * @return
     */
    @Override
    public List<QueryServiceVo> queryServiceProperties(String iotId) {
        ShowDeviceShadowRequest request = new ShowDeviceShadowRequest();
        request.withDeviceId(iotId);
        try {
            ShowDeviceShadowResponse response = client.showDeviceShadow(request);
            if (ObjectUtil.isNull(response)){
                throw new BaseException("查询失败");
            }
            Map<String, Object> map = (Map<String, Object>) response.getShadow().get(0).getReported().getProperties();
            String eventTime1 = response.getShadow().get(0).getReported().getEventTime();
            LocalDateTime eventTime =  LocalDateTimeUtil.parse(eventTime1, "yyyyMMdd'T'HHmmss'Z'");
            LocalDateTime alarmTime = eventTime.atZone(ZoneId.from(ZoneOffset.UTC))
                                              .withZoneSameInstant(ZoneId.of("Asia/Shanghai"))
                                              .toLocalDateTime();
            List<QueryServiceVo> queryServiceVos = new ArrayList<>();
            map.forEach((k,v)->{
                QueryServiceVo queryServiceVo = new QueryServiceVo();
                queryServiceVo.setFunctionId(k);
                if (ObjectUtil.isEmpty(v)) {
                    queryServiceVo.setValue(70);
                } else if (v instanceof String && NumberUtil.isNumber((String) v)) {
                    queryServiceVo.setValue(Integer.parseInt((String) v));
                } else if (v instanceof Integer) {
                    queryServiceVo.setValue((Integer) v);
                } else {
                    queryServiceVo.setValue(70); // 默认兜底值
                }
                queryServiceVo.setEventTime(alarmTime);
                queryServiceVos.add(queryServiceVo);
            });
            return queryServiceVos;
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("查询失败");
        }
    }

    /*
     *  按天统计查询指标数据
     * 根据ai生成
     * */

    @Override
    public List<DeviceDataVo> queryDeviceDataListByDay(queryDeviceDataListByDayDto vo) {
        //1.获取设备id和物模型id
        String iotId = vo.getIotId();
        String functionId = vo.getFunctionId();
        //2.获取开始时间和结束时间
        LocalDateTime startTime = LocalDateTime.ofInstant(
                Instant.ofEpochMilli(vo.getStartTime()), ZoneId.systemDefault());
        LocalDateTime endTime = LocalDateTime.ofInstant(
                Instant.ofEpochMilli(vo.getEndTime()), ZoneId.systemDefault());
        //3.获取物模型数据
        List<DeviceData> deviceData1 = deviceDataMapper.selectList(
                new LambdaQueryWrapper<DeviceData>()
                        .eq(DeviceData::getIotId, iotId)
                        .eq(DeviceData::getFunctionId,functionId)
                        .between(DeviceData::getAlarmTime, startTime, endTime)
        );
        //按照小时分组
        List<DeviceDataVo> result = new ArrayList<>();

        // 计算每个小时的平均值
        Map<Integer, Double> avgMap = deviceData1.stream()
                .collect(Collectors.groupingBy(
                        data -> data.getAlarmTime().getHour(),
                        Collectors.averagingDouble(data -> Double.parseDouble(data.getDataValue()))
                ));

        // 填充结果
        for (int hour = 0; hour < 24; hour++) {
            DeviceDataVo voItem = new DeviceDataVo();
            voItem.setDateTime(String.format("%02d:00", hour));
            voItem.setDataValue(avgMap.getOrDefault(hour, 0.0));
            result.add(voItem);
        }
        return result;
    }

    @Override
    public List<DeviceDataVo> queryDeviceDataListByWeek(queryDeviceDataListByDayDto vo) {
        //1.获取设备id和物模型id
        String iotId = vo.getIotId();
        String functionId = vo.getFunctionId();
//        获取当前日期
        LocalDateTime now = LocalDateTime.now();
//        查询过去 7 天的数据（包括今天）
        LocalDateTime startTime = now.minusDays(6).toLocalDate().atStartOfDay();
        LocalDateTime endTime = now.toLocalDate().atStartOfDay().plusDays(1);
//        按天分组
        List<DeviceData> deviceData = deviceDataMapper.selectList(new LambdaQueryWrapper<DeviceData>()
                .eq(DeviceData::getIotId, iotId)
                .eq(DeviceData::getFunctionId,functionId)
                .between(DeviceData::getAlarmTime, startTime, endTime));
//        对每天的数据求平均/最大/最小等（根据业务需求）
        Map<LocalDate, Double> collect = deviceData.stream().collect(Collectors.groupingBy(
                data -> data.getAlarmTime().toLocalDate(),
                Collectors.averagingDouble(data -> Double.parseDouble(data.getDataValue()))
        ));
        List<DeviceDataVo> result = new ArrayList<>();
        for (int i = 0; i < 7; i++){
            LocalDate date = now.minusDays(6 - i).toLocalDate();
            DeviceDataVo deviceDataVo = new DeviceDataVo();
            deviceDataVo.setDateTime(date.format(DateTimeFormatter.ofPattern("MM.dd")));
            deviceDataVo.setDataValue((double) collect.getOrDefault(date, 0.0).intValue());
            result.add(deviceDataVo);
        }

        return result;
    }
}


